// linux_manager.go
package service

import (
	"bufio"
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
)

// LinuxServiceManager Linux 服务管理器
type LinuxServiceManager struct {
	sudoRequired bool
}

// NewLinuxServiceManager 创建 Linux 服务管理器
func NewLinuxServiceManager() *LinuxServiceManager {
	return &LinuxServiceManager{
		sudoRequired: os.Getuid() != 0, // 非 root 用户需要 sudo
	}
}

// Status 获取 Linux 服务状态
func (lsm *LinuxServiceManager) Status(serviceName string) (*ServiceInfo, error) {
	cmd := lsm.buildCommand("systemctl", "status", serviceName)

	output, err := cmd.CombinedOutput()
	if err != nil {
		// systemctl status 在服务不存在或停止时返回非零退出码，但我们仍然需要解析输出
		return lsm.parseServiceStatus(serviceName, string(output)), nil
	}

	return lsm.parseServiceStatus(serviceName, string(output)), nil
}

// Start 启动 Linux 服务
func (lsm *LinuxServiceManager) Start(serviceName string) error {
	cmd := lsm.buildCommand("systemctl", "start", serviceName)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("failed to start service %s: %v, output: %s", serviceName, err, string(output))
	}
	return nil
}

// Stop 停止 Linux 服务
func (lsm *LinuxServiceManager) Stop(serviceName string) error {
	cmd := lsm.buildCommand("systemctl", "stop", serviceName)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("failed to stop service %s: %v, output: %s", serviceName, err, string(output))
	}
	return nil
}

// Restart 重启 Linux 服务
func (lsm *LinuxServiceManager) Restart(serviceName string) error {
	cmd := lsm.buildCommand("systemctl", "restart", serviceName)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("failed to restart service %s: %v, output: %s", serviceName, err, string(output))
	}
	return nil
}

// List 列出所有 Linux 服务
func (lsm *LinuxServiceManager) List() ([]ServiceInfo, error) {
	cmd := lsm.buildCommand("systemctl", "list-units", "--type=service", "--all", "--no-pager")
	output, err := cmd.Output()
	if err != nil {
		return nil, fmt.Errorf("failed to list services: %v", err)
	}

	var services []ServiceInfo
	scanner := bufio.NewScanner(bytes.NewReader(output))

	// 跳过标题行
	for i := 0; i < 1; i++ {
		if !scanner.Scan() {
			break
		}
	}

	for scanner.Scan() {
		line := scanner.Text()
		if strings.TrimSpace(line) == "" {
			continue
		}

		service := lsm.parseServiceLine(line)
		if service != nil {
			services = append(services, *service)
		}
	}

	return services, nil
}

// Logs 获取 Linux 服务日志
func (lsm *LinuxServiceManager) Logs(serviceName string, lines int) (string, error) {
	args := []string{"journalctl", "-u", serviceName}

	if lines > 0 {
		args = append(args, "-n", strconv.Itoa(lines))
	}

	cmd := lsm.buildCommand(args[0], args[1:]...)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return "", fmt.Errorf("failed to get logs for service %s: %v", serviceName, err)
	}

	return string(output), nil
}

// IsRunning 检查服务是否运行
func (lsm *LinuxServiceManager) IsRunning(serviceName string) (bool, error) {
	service, err := lsm.Status(serviceName)
	if err != nil {
		return false, err
	}
	return service.State == "running", nil
}

// Enable 启用 Linux 服务（开机自启）
func (lsm *LinuxServiceManager) Enable(serviceName string) error {
	cmd := lsm.buildCommand("systemctl", "enable", serviceName)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("failed to enable service %s: %v, output: %s", serviceName, err, string(output))
	}
	return nil
}

// Disable 禁用 Linux 服务（开机自启）
func (lsm *LinuxServiceManager) Disable(serviceName string) error {
	cmd := lsm.buildCommand("systemctl", "disable", serviceName)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("failed to disable service %s: %v, output: %s", serviceName, err, string(output))
	}
	return nil
}

// parseServiceStatus 解析 systemctl status 输出
func (lsm *LinuxServiceManager) parseServiceStatus(serviceName, output string) *ServiceInfo {
	service := &ServiceInfo{Name: serviceName}

	lines := strings.Split(output, "\n")
	for _, line := range lines {
		line = strings.TrimSpace(line)

		// 解析服务描述
		if strings.HasPrefix(line, "●") {
			parts := strings.Fields(line)
			if len(parts) > 1 {
				service.Description = strings.Join(parts[1:], " ")
			}
		}

		// 解析 Active 状态
		if strings.HasPrefix(line, "Active:") {
			re := regexp.MustCompile(`Active:\s+(\w+)\s+\((.*?)\)`)
			matches := re.FindStringSubmatch(line)
			if len(matches) == 3 {
				service.State = matches[1]
				service.Status = lsm.mapLinuxStatus(matches[1])
			}
		}

		// 解析 PID
		if strings.Contains(line, "Main PID:") {
			re := regexp.MustCompile(`Main PID:\s+(\d+)`)
			matches := re.FindStringSubmatch(line)
			if len(matches) == 2 {
				pid, _ := strconv.Atoi(matches[1])
				service.PID = pid
			}
		}

		// 解析内存
		if strings.Contains(line, "Memory:") {
			re := regexp.MustCompile(`Memory:\s+(.+)`)
			matches := re.FindStringSubmatch(line)
			if len(matches) == 2 {
				service.Memory = matches[1]
			}
		}

		// 解析 CPU
		if strings.Contains(line, "CPU:") {
			re := regexp.MustCompile(`CPU:\s+(.+)`)
			matches := re.FindStringSubmatch(line)
			if len(matches) == 2 {
				service.CPU = matches[1]
			}
		}
	}

	return service
}

// parseServiceLine 解析服务列表行
func (lsm *LinuxServiceManager) parseServiceLine(line string) *ServiceInfo {
	fields := strings.Fields(line)
	if len(fields) < 5 {
		return nil
	}

	serviceName := fields[0]
	description := strings.Join(fields[1:len(fields)-3], " ")
	status := fields[len(fields)-3]

	service := &ServiceInfo{
		Name:        serviceName,
		Description: description,
		Status:      lsm.mapLinuxStatus(status),
		State:       status,
	}

	return service
}

// mapLinuxStatus 映射 Linux 服务状态
func (lsm *LinuxServiceManager) mapLinuxStatus(linuxStatus string) string {
	switch strings.ToLower(linuxStatus) {
	case "active", "running":
		return "running"
	case "inactive", "dead":
		return "stopped"
	case "activating", "starting":
		return "starting"
	case "deactivating", "stopping":
		return "stopping"
	case "failed":
		return "failed"
	default:
		return linuxStatus
	}
}

// buildCommand 构建命令，处理 sudo 需求
func (lsm *LinuxServiceManager) buildCommand(name string, args ...string) *exec.Cmd {
	if lsm.sudoRequired {
		fullArgs := append([]string{name}, args...)
		return exec.Command("sudo", fullArgs...)
	}
	return exec.Command(name, args...)
}
